package com.ly.mpayment.persist.socket.send;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.xsocket.MaxReadSizeExceededException;
import org.xsocket.connection.IConnectHandler;
import org.xsocket.connection.IConnectionTimeoutHandler;
import org.xsocket.connection.IDataHandler;
import org.xsocket.connection.IDisconnectHandler;
import org.xsocket.connection.IIdleTimeoutHandler;
import org.xsocket.connection.INonBlockingConnection;





@Component
public class SocketHandler  implements IDataHandler,IConnectHandler,
IDisconnectHandler,IConnectionTimeoutHandler,IIdleTimeoutHandler{
	 private final Log log = LogFactory.getLog(this.getClass());
	/**
	 * 存放连接的map
	 */
	private ConcurrentMap<String, INonBlockingConnection> connections = new ConcurrentHashMap<String, INonBlockingConnection>();
	
	private static final String POLICY = "<?xml version=\"1.0\" encoding=\"utf-8\"?><!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>";

	
	/**
	 * 处理接收到的数据
	 */
	
	public boolean onData(INonBlockingConnection connection) throws IOException,
			BufferUnderflowException, ClosedChannelException,
			MaxReadSizeExceededException { 
		connection.write(POLICY+"\0");
		connection.flush();
		return true;
	}
	
	/**
	 * 当链接到来时执行
	 */
	
	public boolean onConnect(INonBlockingConnection connection) throws IOException,
			BufferUnderflowException, MaxReadSizeExceededException {
		log.info("打开连接：ip地址为"+connection.getRemoteAddress() + ", id="+connection.getId());
		this.connections.put(connection.getId(), connection);
		/*无需再此做安全校验，在onData中进行安全验证
		connection.write(POLICY+"\0");
		connection.flush();
		*/
		return true;
	}
	
	public void sendData(String data){
		Set<String> keySet = this.connections.keySet();
		for(String key:keySet){
			try {
				INonBlockingConnection con = this.connections.get(key);
				con.write(data);
				con.flush();
				log.info("信息发送:"+data);
			} catch (SocketTimeoutException e) {
				log.info(e);
			} catch (ClosedChannelException e) {
				log.info(e);
			} catch (IOException e) {
				log.info(e);
			}
		}
	}
	
	/**
	 * 将buffer重新移位，清除错误的数据
	 * @param buffer
	 * @param position
	 * @param wrapLength
	 */
//	private void clearBuffer(ByteBuffer buffer, int position, int wrapLength){
//		int length = wrapLength-position;
//		buffer.clear();
//		for(int i=0; i<length; i++){
//			buffer.put(buffer.get(position++));
//			buffer.position(i+1);
//		}
//	}
	
	/**
	 * 当链接断开时将链接从connections中移除
	 */
	
	public boolean onDisconnect(INonBlockingConnection connection) throws IOException {
		Iterator<String> it = this.connections.keySet().iterator();
		while(it.hasNext()){
			String key = it.next();
			if(connection.getId() == key){
				log.info("移除连接：ip地址为"+connection.getRemoteAddress() + ", id="+connection.getId());
				it.remove();
				break;
			}
		}
		
		connection.close();
		return false;
	}
	/**
	 * 链接超时，将链接移除
	 */
	
	public boolean onConnectionTimeout(INonBlockingConnection connection)
			throws IOException {
		Iterator<String> it = this.connections.keySet().iterator();
		while(it.hasNext()){
			String key = it.next();
			if(connection.getId() == key){
				log.info("超时移除连接：ip地址为"+connection.getRemoteAddress() + ", id="+connection.getId());
				it.remove();
				break;
			}
		}
		
		connection.close();
		return false;
	}
	

	/**
	 * 当连接空闲时间超时则断开连接
	 */
	
	public boolean onIdleTimeout(INonBlockingConnection connection)
			throws IOException {
		Iterator<String> it = this.connections.keySet().iterator();
		while(it.hasNext()){
			String key = it.next();
			if(connection.getId() == key){
				log.info("移除空闲连接：ip地址为"+connection.getRemoteAddress() + ", id="+connection.getId());
				it.remove();
				break;
			}
		}
		
		connection.close();
		return false;
	}

}
